<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="jM2Xg" id="jM2Xg"><span data-lake-id="ub632a11d" id="ub632a11d">典型回答</span></h1>
  <p data-lake-id="u8e9dbf6a" id="u8e9dbf6a"><br></p>
  <p data-lake-id="ub7b916e1" id="ub7b916e1"><span data-lake-id="u5ff85d15" id="u5ff85d15">ZooKeeper的选举机制是其实现分布式协调一致性的核心部分，它确保在ZooKeeper集群中选择一个Leader节点来协调和处理客户端请求。</span></p>
  <p data-lake-id="ufb7cfcdd" id="ufb7cfcdd"><span data-lake-id="u8e6c2f93" id="u8e6c2f93">​</span><br></p>
  <p data-lake-id="uee846412" id="uee846412"><span data-lake-id="u19b6b62e" id="u19b6b62e">一次完整的选举大概要经历以下几个步骤：</span></p>
  <p data-lake-id="uc7b3fdfe" id="uc7b3fdfe"><span data-lake-id="u4fcab46e" id="u4fcab46e">​</span><br></p>
  <p data-lake-id="u0e8cd02a" id="u0e8cd02a"><strong><span data-lake-id="u9ff8d68d" id="u9ff8d68d">初始化阶段</span></strong><span data-lake-id="uc06cbe66" id="uc06cbe66">： 在一个ZooKeeper集群中，每个Follower节点都可以成为Leader。初始状态下，所有Follower节点都是处于"LOOKING"状态，即寻找Leader。每个节点都会监视集群中的其他节点，以侦听Leader选举消息。</span></p>
  <p data-lake-id="ue038246a" id="ue038246a"><span data-lake-id="ub4544df8" id="ub4544df8">​</span><br></p>
  <p data-lake-id="uc6843f13" id="uc6843f13"><strong><span data-lake-id="uc6dc2fa9" id="uc6dc2fa9">提名和投票</span></strong><span data-lake-id="u93a0a77f" id="u93a0a77f">： 当一个节点启动时，它会向其他节点发送投票请求，称为提名。节点收到提名后可以选择投票支持这个提名节点，也可以不投票。每个节点只能在一个选举周期内投出一票。</span></p>
  <p data-lake-id="u78f16701" id="u78f16701"><span data-lake-id="ufeadd78e" id="ufeadd78e">​</span><br></p>
  <p data-lake-id="u5fa799ef" id="u5fa799ef"><span data-lake-id="ub9cce322" id="ub9cce322">在提名过程中，所有的投票者都遵守一个原则，那就是</span><strong><span data-lake-id="u7ce45c9b" id="u7ce45c9b">遇强投强</span></strong><span data-lake-id="ubb8c211d" id="ubb8c211d">。</span></p>
  <p data-lake-id="ucc6da220" id="ucc6da220"><span data-lake-id="u12c6cbdf" id="u12c6cbdf">​</span><br></p>
  <p data-lake-id="u16446b8e" id="u16446b8e"><strong><span data-lake-id="u1d6216cc" id="u1d6216cc">怎么算强？</span></strong></p>
  <p data-lake-id="uf8095aee" id="uf8095aee"><span data-lake-id="uc6e25d22" id="uc6e25d22">​</span><br></p>
  <p data-lake-id="u1c8e257d" id="u1c8e257d"><span data-lake-id="u44aa2736" id="u44aa2736">在Zookeeper中，通过数据是否足够新来判断这个节点是不是够强。在 Zookeeper 中以事务id（zxid）来标识数据的新旧程度，节点的zxid越大代表这个节点的数据越新，也就代表这个节点能力越强。</span></p>
  <p data-lake-id="u0494ffd5" id="u0494ffd5"><span data-lake-id="u39b5a325" id="u39b5a325">​</span><br></p>
  <p data-lake-id="uc52a53c2" id="uc52a53c2"><span data-lake-id="ue7bff122" id="ue7bff122">那么在投票过程中，节点首先会认为自己是最强的，所以他会在投票时先投自己一票，然后把自己的投票信息广播出去，这里面包含了</span><strong><span data-lake-id="u22e1af70" id="u22e1af70">zxid</span></strong><span data-lake-id="u95f70538" id="u95f70538">和</span><strong><span data-lake-id="uc6a36810" id="uc6a36810">sid</span></strong><span data-lake-id="u174c7fa0" id="u174c7fa0">，zxid就是自己的事务ID，sid就是标识出自己是谁的唯一标识。</span></p>
  <p data-lake-id="u0d16020e" id="u0d16020e"><span data-lake-id="u578e3dff" id="u578e3dff">​</span><br></p>
  <p data-lake-id="u19ab1dc8" id="u19ab1dc8"><span data-lake-id="uc309548e" id="uc309548e">这样集群中的节点们就会不断受到别人发过来的投票结果，然后这个节点就会拿别人的zxid和自己的zxid进行比较，如果别人的zxid更大， 说明他的数据更新，那么就会重新投票，把zxid和sid都换成别人的信息再发出去。</span></p>
  <p data-lake-id="u11b47d6d" id="u11b47d6d"><span data-lake-id="u1ed20df7" id="u1ed20df7">​</span><br></p>
  <p data-lake-id="uca2de3dc" id="uca2de3dc"><strong><span data-lake-id="udcbe7368" id="udcbe7368">选举过程</span></strong><span data-lake-id="u50b73ede" id="u50b73ede">： 选举过程分为多个轮次，每个轮次被称为一个"选举周期"。在每个选举周期中，节点根据投票数来选择新的Leader候选者。如果一个候选者获得了大多数节点（超过半数）的投票，那么它就会成为新的Leader。否则，没有候选者能够获得足够的投票，那么这个选举周期失败，所有节点会继续下一个选举周期。</span></p>
  <p data-lake-id="u308145bc" id="u308145bc"><span data-lake-id="u94f54754" id="u94f54754">​</span><br></p>
  <p data-lake-id="u32fffaf4" id="u32fffaf4"><strong><span data-lake-id="uab9f8fe3" id="uab9f8fe3">Leader确认</span></strong><span data-lake-id="u1446b7c6" id="u1446b7c6">： 一旦一个候选者获得了大多数节点的投票，它就会成为新的Leader。这个Leader会向其他节点发送Leader就绪消息，告知它们自己已经成为Leader，并且开始处理客户端的请求。</span></p>
  <p data-lake-id="u49ddf800" id="u49ddf800"><span data-lake-id="u48ff37d5" id="u48ff37d5">​</span><br></p>
  <p data-lake-id="ueb4f5bee" id="ueb4f5bee"><strong><span data-lake-id="u6d5fccd1" id="u6d5fccd1">集群同步</span></strong><span data-lake-id="u41b4b871" id="u41b4b871">： 一旦新的Leader选举完成，其他节点会与新Leader同步数据，确保所有节点在一个一致的状态下运行。这个同步过程也包括了未完成的客户端请求，以保证数据的一致性。</span></p>
  <p data-lake-id="u9279418a" id="u9279418a"><br></p>
  <h1 data-lake-id="qGFdI" id="qGFdI"><span data-lake-id="uac98373b" id="uac98373b">扩展知识</span></h1>
  <p data-lake-id="uf12b8bc3" id="uf12b8bc3"><br></p>
  <h2 data-lake-id="kn8Cs" id="kn8Cs"><span data-lake-id="ub82c1c57" id="ub82c1c57">选举状态</span></h2>
  <p data-lake-id="u42bc97cc" id="u42bc97cc"><br></p>
  <p data-lake-id="ub0d90552" id="ub0d90552"><span data-lake-id="u380efdee" id="u380efdee">在整个选举过程中，节点的状态可能有4种，分别是</span></p>
  <p data-lake-id="u1372b0c8" id="u1372b0c8"><span data-lake-id="u2dec27fc" id="u2dec27fc">​</span><br></p>
  <p data-lake-id="ua423698a" id="ua423698a"><span data-lake-id="uf88bcaa3" id="uf88bcaa3">LOOKING</span><span data-lake-id="ud0715f8c" id="ud0715f8c">，竞选状态。</span></p>
  <p data-lake-id="uf7b02468" id="uf7b02468"><span data-lake-id="u4715d389" id="u4715d389">FOLLOWING</span><span data-lake-id="u26ddf0d7" id="u26ddf0d7">，随从状态，同步leader状态，参与投票。</span></p>
  <p data-lake-id="udf73acc0" id="udf73acc0"><span data-lake-id="u2adca434" id="u2adca434">OBSERVING，观察状态，同步leader状态，但是不参与投票。</span></p>
  <p data-lake-id="uf4109279" id="uf4109279"><span data-lake-id="u5cd124eb" id="u5cd124eb">LEADING，领导者状态。</span></p>
  <p data-lake-id="ua475cb33" id="ua475cb33" style="text-align: justify"><span data-lake-id="u8240ba95" id="u8240ba95" style="color: rgb(0, 0, 0)">​</span><br></p>
  <h2 data-lake-id="t6R6k" id="t6R6k"><span data-lake-id="u14dc45a0" id="u14dc45a0">Leader选举的场景</span></h2>
  <p data-lake-id="ufb990261" id="ufb990261"><br></p>
  <p data-lake-id="u829ec546" id="u829ec546"><span data-lake-id="u25889f22" id="u25889f22">ZooKeeper其实会在两种情况下进行Leader选举，第一种是集群的启动阶段，第二个是Leader失效了的情况。</span></p>
  <p data-lake-id="u7be9efc5" id="u7be9efc5"><span data-lake-id="ub6b7a481" id="ub6b7a481">​</span><br></p>
  <p data-lake-id="ud2e99b14" id="ud2e99b14"><strong><span data-lake-id="ufe06ef64" id="ufe06ef64">启动阶段</span></strong><span data-lake-id="ua8072a47" id="ua8072a47">： 当整个ZooKeeper集群启动时，这时候还没有Leader，那么就会进行一次Leader选举。</span></p>
  <p data-lake-id="u23e3b3a3" id="u23e3b3a3"><span data-lake-id="u8faf17b1" id="u8faf17b1">​</span><br></p>
  <p data-lake-id="uc429e196" id="uc429e196"><strong><span data-lake-id="u1d378fa9" id="u1d378fa9">Leader失效</span></strong><span data-lake-id="ud9ac4374" id="ud9ac4374">：如果当前的Leader节点由于某种原因（如宕机、网络故障、连接丢失等）失效，剩余的节点会开始一个新的选举周期来选择新的Leader。</span></p>
  <p data-lake-id="ufae26781" id="ufae26781"><br></p>
  <h3 data-lake-id="IG6YA" id="IG6YA"><span data-lake-id="u5e5ffb60" id="u5e5ffb60">启动阶段的Leader选举</span></h3>
  <p data-lake-id="u8d129aab" id="u8d129aab"><br></p>
  <p data-lake-id="u21dfe576" id="u21dfe576" style="text-align: justify"><span data-lake-id="u785d45c7" id="u785d45c7" style="color: rgb(0, 0, 0)">假设一个 Zookeeper 集群中有5台服务器，id从1到5编号，并且它们都是最新启动的，没有历史数据。</span></p>
  <p data-lake-id="u497affed" id="u497affed" style="text-align: justify"><span data-lake-id="u1e9a77ff" id="u1e9a77ff" style="color: rgb(0, 0, 0)">​</span><br></p>
  <p data-lake-id="u4eed2f15" id="u4eed2f15" style="text-align: left"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1691813532824-bdc3def9-f56e-4e26-9e28-83e59a09cae8.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_31%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ud4cb01fa" id="ud4cb01fa"><span data-lake-id="uf6209b27" id="uf6209b27"><br><br></span></p>
  <p data-lake-id="u25845cd9" id="u25845cd9"><span data-lake-id="u8dff539c" id="u8dff539c">假设服务器依次启动，那么大致的选举过程：</span></p>
  <p data-lake-id="ub8362411" id="ub8362411"><strong><span data-lake-id="u155503d9" id="u155503d9">服务器1启动</span></strong><span data-lake-id="u67581ef9" id="u67581ef9">，进入LOOKING状态，开始发起投票，服务器1投自己一票，&lt;zxid=1,sid=1&gt;</span></p>
  <p data-lake-id="uce524319" id="uce524319"><span data-lake-id="u4dc5b20d" id="u4dc5b20d">​</span><br></p>
  <blockquote data-lake-id="u49a70870" id="u49a70870">
   <p data-lake-id="ufd877748" id="ufd877748"><span data-lake-id="u8898144d" id="u8898144d">投票结果：服务器1，1票</span></p>
   <p data-lake-id="u211e8440" id="u211e8440"><span data-lake-id="uf8846cc1" id="uf8846cc1">服务器1状态：LOOKING</span></p>
  </blockquote>
  <p data-lake-id="u8e4885d9" id="u8e4885d9"><span data-lake-id="u47aee881" id="u47aee881">​</span><br></p>
  <p data-lake-id="u9acca587" id="u9acca587"><span data-lake-id="uee7a9833" id="uee7a9833">因为投票总数未过半，则继续选举。</span></p>
  <p data-lake-id="uce44df39" id="uce44df39"><span data-lake-id="u96a5474b" id="u96a5474b">​</span><br></p>
  <p data-lake-id="ue6c56711" id="ue6c56711"><strong><span data-lake-id="ua3e8ed7a" id="ua3e8ed7a">服务器2启动</span></strong><span data-lake-id="ub852f5c1" id="ub852f5c1">，进入LOOKING状态，开始投票，服务器2投自己一票&lt;zxid=2,sid=2&gt;，并收到服务器1的投票&lt;zxid=1,sid=1&gt;。同时服务器1也收到服务器2的投票&lt;zxid=2,sid=2&gt;，经比对，服务器2的zxid更大，于是服务器1改票&lt;zxid=2,sid=2&gt;</span></p>
  <p data-lake-id="ub372d963" id="ub372d963"><span data-lake-id="ubf2ecc2e" id="ubf2ecc2e">​</span><br></p>
  <blockquote data-lake-id="u6b4f6879" id="u6b4f6879">
   <p data-lake-id="u94c46557" id="u94c46557"><span data-lake-id="ubb856c0a" id="ubb856c0a">投票结果：服务器2，2票</span></p>
   <p data-lake-id="u41c6b063" id="u41c6b063"><span data-lake-id="u1cb2fc69" id="u1cb2fc69">服务器1状态：LOOKING</span></p>
   <p data-lake-id="ubb6f3547" id="ubb6f3547"><span data-lake-id="u7a7f9c13" id="u7a7f9c13">服务器2状态：LOOKING</span></p>
  </blockquote>
  <p data-lake-id="ud149e4da" id="ud149e4da"><br></p>
  <p data-lake-id="ue95e8cc9" id="ue95e8cc9"><span data-lake-id="u597d69b7" id="u597d69b7">因为投票总数未过半，则继续选举。</span></p>
  <p data-lake-id="u0fd3b1a9" id="u0fd3b1a9"><span data-lake-id="u69ebbba2" id="u69ebbba2">​</span><br></p>
  <p data-lake-id="u5514cf6d" id="u5514cf6d"><strong><span data-lake-id="uc31e7330" id="uc31e7330">服务器3启动</span></strong><span data-lake-id="u0ef58df4" id="u0ef58df4">，同样经过和服务器2一样的过程，之后服务器1，服务器2开始改投服务器3，</span></p>
  <p data-lake-id="u5b4b12fa" id="u5b4b12fa"><span data-lake-id="u5d807f08" id="u5d807f08">发起一次选举，服务器1、2、3先投自己一票，然后因为服务器3的id最大，两者更改选票投给为服务器3；</span></p>
  <p data-lake-id="uba637ab4" id="uba637ab4"><span data-lake-id="uccbbd44a" id="uccbbd44a">​</span><br></p>
  <blockquote data-lake-id="u8f3f45e6" id="u8f3f45e6">
   <p data-lake-id="ue5b2edcf" id="ue5b2edcf"><span data-lake-id="u338b73c3" id="u338b73c3">投票结果：服务器3，3票</span></p>
   <p data-lake-id="u2d1ad5d6" id="u2d1ad5d6"><span data-lake-id="u867d43ad" id="u867d43ad">服务器1状态：FOLLOWING</span></p>
   <p data-lake-id="u8b192ff8" id="u8b192ff8"><span data-lake-id="ue9d20ee1" id="ue9d20ee1">服务器2状态：FOLLOWING</span></p>
   <p data-lake-id="u5f44b9b8" id="u5f44b9b8"><span data-lake-id="uafd4f990" id="uafd4f990">服务器3状态：LEADING</span></p>
  </blockquote>
  <p data-lake-id="u83d43f2b" id="u83d43f2b"><br></p>
  <p data-lake-id="uf087686f" id="uf087686f"><strong><span data-lake-id="u7fa5b4d0" id="u7fa5b4d0">服务器4启动</span></strong><span data-lake-id="u63592d7a" id="u63592d7a">，发现集群中已经有Leader，则自己变为Follower，进入FOLLOWING状态。</span></p>
  <p data-lake-id="u508d65c0" id="u508d65c0"><span data-lake-id="uef5c6cfb" id="uef5c6cfb">​</span><br></p>
  <blockquote data-lake-id="u1a9a5796" id="u1a9a5796">
   <p data-lake-id="uecfa54b3" id="uecfa54b3"><span data-lake-id="u33e6303d" id="u33e6303d">服务器1状态：FOLLOWING</span></p>
   <p data-lake-id="u396d5458" id="u396d5458"><span data-lake-id="ucb3b4685" id="ucb3b4685">服务器2状态：FOLLOWING</span></p>
   <p data-lake-id="ubcffd7f0" id="ubcffd7f0"><span data-lake-id="ubc15ed36" id="ubc15ed36">服务器3状态：LEADING</span></p>
   <p data-lake-id="uf1090256" id="uf1090256"><span data-lake-id="u856b9bf1" id="u856b9bf1">服务器4状态：FOLLOWING</span></p>
  </blockquote>
  <p data-lake-id="u9a72a110" id="u9a72a110"><br></p>
  <p data-lake-id="u53297760" id="u53297760"><br></p>
  <p data-lake-id="uf21cb6a8" id="uf21cb6a8"><strong><span data-lake-id="uea43f19e" id="uea43f19e">服务器5启动，</span></strong><span data-lake-id="ud7fdbd3b" id="ud7fdbd3b">和服务器4一样，进入FOLLOWTING状态。</span></p>
  <p data-lake-id="ua83819ca" id="ua83819ca"><span data-lake-id="u1f11d14c" id="u1f11d14c">​</span><br></p>
  <blockquote data-lake-id="uf197e6a3" id="uf197e6a3">
   <p data-lake-id="u33866b3b" id="u33866b3b"><span data-lake-id="u8a89de8f" id="u8a89de8f">服务器1状态：FOLLOWING</span></p>
   <p data-lake-id="uc2ce463b" id="uc2ce463b"><span data-lake-id="uf4371df6" id="uf4371df6">服务器2状态：FOLLOWING</span></p>
   <p data-lake-id="u1cfc3ee5" id="u1cfc3ee5"><span data-lake-id="u77ce761c" id="u77ce761c">服务器3状态：LEADING</span></p>
   <p data-lake-id="u3cf09db4" id="u3cf09db4"><span data-lake-id="u00496024" id="u00496024">服务器4状态：FOLLOWING</span></p>
   <p data-lake-id="ue7e4580e" id="ue7e4580e"><span data-lake-id="u6bf6d994" id="u6bf6d994">服务器5状态：FOLLOWING</span></p>
  </blockquote>
  <p data-lake-id="u08f65bba" id="u08f65bba"><span data-lake-id="uc90e0de3" id="uc90e0de3">​</span><br></p>
  <p data-lake-id="u57eaeda9" id="u57eaeda9"><span data-lake-id="u0e9d02ec" id="u0e9d02ec">至此，完成Leader选举，服务器3当选！ </span></p>
  <p data-lake-id="u80455ef2" id="u80455ef2"><span data-lake-id="u0bd86a05" id="u0bd86a05">​</span><br></p>
  <p data-lake-id="u3a1fd3e6" id="u3a1fd3e6"><span data-lake-id="u50a3498d" id="u50a3498d">​</span><br></p>
  <h3 data-lake-id="pHI8n" id="pHI8n"><span data-lake-id="u829ee8b6" id="u829ee8b6">Leader失效重新选举</span></h3>
  <p data-lake-id="ub4ef75b2" id="ub4ef75b2"><br></p>
  <p data-lake-id="u9882991b" id="u9882991b" style="text-align: justify"><span data-lake-id="uf159f559" id="uf159f559">初始状态下服务器3当选为Leader，此时每个服务器上zxid可能都不一样，server1为99，server2为102，server4为100，server5为101，假设现在服务器3故障宕机了</span></p>
  <p data-lake-id="uc8747bbf" id="uc8747bbf" style="text-align: justify"><span data-lake-id="u5e2d2847" id="u5e2d2847" style="color: rgb(0, 0, 0)">​</span><br></p>
  <p data-lake-id="ua48001ce" id="ua48001ce" style="text-align: left"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1691814117118-54773c68-4c6c-43eb-be78-865cd2ea3794.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_31%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ue21c6185" id="ue21c6185"><span data-lake-id="u1122ced9" id="u1122ced9">​</span><br></p>
  <p data-lake-id="uab027b1f" id="uab027b1f"><span data-lake-id="u1663fc97" id="u1663fc97">服务器3宕机后，各个Follower节点会进入到LOOKING状态，开始进行选举投票。</span></p>
  <p data-lake-id="ubf6bf9a0" id="ubf6bf9a0"><span data-lake-id="u609b85bf" id="u609b85bf">​</span><br></p>
  <p data-lake-id="ud76cc255" id="ud76cc255"><span data-lake-id="uef54f370" id="uef54f370">每个服务器都会投自己一票，并且把自己的选票都广播出去：</span></p>
  <p data-lake-id="uf7d42cc8" id="uf7d42cc8"><span data-lake-id="u22e73e58" id="u22e73e58">&lt;zxid=88,sid=1&gt;</span></p>
  <p data-lake-id="u4c19be20" id="u4c19be20"><span data-lake-id="u644c59c4" id="u644c59c4">&lt;zxid=102,sid=2&gt;</span></p>
  <p data-lake-id="u825e258e" id="u825e258e"><span data-lake-id="ue865a622" id="ue865a622">&lt;zxid=100,sid=4&gt;</span></p>
  <p data-lake-id="u8cf6de32" id="u8cf6de32"><span data-lake-id="uce426b38" id="uce426b38">&lt;zxid=101,sid=5&gt;</span></p>
  <p data-lake-id="uef74b591" id="uef74b591"><span data-lake-id="ua6ae6b33" id="ua6ae6b33">​</span><br></p>
  <p data-lake-id="u0a83ed85" id="u0a83ed85"><span data-lake-id="ue3892348" id="ue3892348">并且所有人在接收到其他的人投票后，会根据选票情况进行改选，最终zxid=102的这个服务器会当选。<br><br></span></p>
  <p data-lake-id="ubd1c5f04" id="ubd1c5f04"><span data-lake-id="u41cc7dfd" id="u41cc7dfd">​</span><br></p>
  <p data-lake-id="u303c8ddb" id="u303c8ddb"><span data-lake-id="u203d5335" id="u203d5335">PS：本文中的例子参考 ： </span><a href="https://mp.weixin.qq.com/s/wOcnhF5AjMXliXAmroYSLA" target="_blank" data-lake-id="u38b8c5f8" id="u38b8c5f8"><span data-lake-id="ub54be50b" id="ub54be50b">https://mp.weixin.qq.com/s/wOcnhF5AjMXliXAmroYSLA</span></a></p>
 </body>
</html>